<!---瀑布流--->
<template>
  <ul class="waterfallWrap" id="afWrap">
    <li class="wfItem" v-for="dt in lists" :key="dt._id">
      <a>
        <img :src="dt[keySrc]"/>
        <p>{{dt.title}}</p>
      </a>
    </li>
  </ul>
</template>

<script>
import { reactive,toRefs,onMounted,getCurrentInstance,computed, nextTick,watch } from 'vue'
export default {
  props:{
    lists:Array,
    spacing:{ // 元素间的间距，单位为px
      type:Number,
      default:10 
    },
    keySrc:{ // 指定的图片路径字段名
      type:String,
      default:'imageUrl'
    },
    perLine:{ // 每行显示个数，默认每行显示2个(目前代码只实现2列)
      type:Number,
      default:2
    }
  },
  setup(props,context){
    const {proxy} = getCurrentInstance()

    const state = reactive({
      dataLists:[],
      calculatedLis:[],//记录已经计算过位置的li对应的ref数组，避免重复计算

      hInfo:{}  // 记录每一列的高度
    })

    watch(()=>props.lists,(newData,oldData) =>{  // 监听属性值变化
      initData(newData)
    })

    onMounted(async()=>{
      initData(state.lists)
    })

    const initData = async(arr)=>{
      if(!arr) return
      const afterLoadImgData = []
      //const arr = props.lists || state.lists
      for(let i =0;i<arr.length;i++){
        let item = arr[i]
        if(item[props.keySrc]){  // 图片路径存在
            if(item.imgIsLoaded){ // 图片已经加载过了
              afterLoadImgData.push(item)
            }else{
              await loadImg(item[props.keySrc])  // 加载图片
              afterLoadImgData.push({...item,imgIsLoaded:true})
            } 
        }
        if(arr.length == afterLoadImgData.length){ // 已经把图片加载完成
          state.dataLists = [...state.dataLists,...afterLoadImgData]
          get_ele_li()
        }
      }
    }

    const loadImg = (imgUrl)=>{
      return new Promise((resolve,reject) =>{
        let img = new Image(); // 创建图片
        img.src = imgUrl;
        img.onload = function() { // 图片加载成功，即下载完成
            resolve(true)
        }
      })
    }

    const get_ele_li = async()=>{ // 获取li元素
        await nextTick()  // 等待文档渲染完毕
        const lis = document.getElementsByClassName('wfItem')  // 获取所有的li
        const out_wrap = document.getElementById('afWrap')  // 外层容器：ul
        const w = out_wrap.offsetWidth / props.perLine  // 计算每li个元素的宽度
        for(let m=0;m<lis.length;m++){
          const li = lis[m]
          li.setAttribute('id',`li_${m+1}`) // 设置li的id属性
          li.style.width = w+'px'  // 设置li宽度
          li.style['padding-top'] = props.spacing + 'px'
          calculate(m+1,li,w)
        }
    }

    const calculate = (index,ele,w)=>{  // 计算元素位置
        setTimeout(()=>{
            //const ele = document.getElementById(id)
            if(!ele) return
            
            // 还没有计算的id对应的li的位置的，则计算
            // const itemObj = state.calculatedLis.find(item => item.id == id)
            // if(!itemObj){
              let left=0,top=0
              //const h = ele.offsetHeight // 计算元素的高度
              
              //const residual = index % props.perLine

              if(props.perLine == 2){  // 每行显示2个时
                if(index==1){ // 第1个li
                    left = 0
                    top = 0
                    setPadding(ele,'l')
                    state.hInfo['h1'] = ele.offsetHeight  // 记录第2列的高度
                }else if(index==2){// 第2个li
                    left = w
                    top = 0
                    setPadding(ele,'r')
                    state.hInfo['h2'] = ele.offsetHeight  // 记录第2列的高度
                }else{ //第2个以后的li
                    if(state.hInfo['h1']>state.hInfo['h2']){
                      // 放在第二列位置
                      left = w
                      top = state.hInfo['h2']
                      setPadding(ele,'r')
                      // 更新第二列的高度
                      state.hInfo['h2'] = state.hInfo['h2'] + ele.offsetHeight
                    }else{
                      // 放在第一列的位置
                      left = 0
                      top = state.hInfo['h1']
                      setPadding(ele,'l')
                      // 更新第一列的高度
                      state.hInfo['h1'] = state.hInfo['h1'] + ele.offsetHeight
                    }
                } 
              }
              const obj = {index,w,left,top,h:ele.offsetHeight}
              state.calculatedLis.push(obj)  // 保存位置信息
              //console.log("calculatedLis:",state.calculatedLis)

              ele.style.top = `${top}px`
              ele.style.left = `${left}px`
              ele.style.height = `${ele.offsetHeight}px`
              document.getElementById('afWrap').style.height = (state.hInfo['h1']>state.hInfo['h2']?`${state.hInfo['h1']}px`:`${state.hInfo['h2']}px`)
            //}
            
        },300)  
    }

    const setPadding = (ele,flag)=>{
      if(flag=='l'){// 左边列
        ele.style['padding-left'] = props.spacing + 'px' //设置边距
        ele.style['padding-right'] = (props.spacing/2) + 'px' //设置边距
      }else if(flag=='r'){// 右边列
        ele.style['padding-left'] = (props.spacing/2) + 'px' //设置边距
        ele.style['padding-right'] = props.spacing + 'px' //设置边距
      }
    }

    return {
      ...toRefs(state)
    }

  }
}
</script>

<style lang="scss" scoped>
  .waterfallWrap{
    width: 100%;
    position: relative;
    z-index: 10;
    li{
      position: absolute;
      z-index: 10;
      img{
        display: block;
        width: 100%;
      }
      a{
        display: block;
      }
    }
  }
</style>